package com.filldream.fastboot.core.manager;

import cn.hutool.core.lang.tree.Tree;
import cn.hutool.core.lang.tree.TreeNodeConfig;
import cn.hutool.core.lang.tree.TreeUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.filldream.fastboot.base.entity.Menu;
import com.filldream.fastboot.base.entity.RoleMenu;
import com.filldream.fastboot.base.mapper.MenuMapper;
import com.filldream.fastboot.base.mapper.RoleMenuMapper;
import com.filldream.fastboot.base.request.pc.menu.MoveMenuSTO;
import com.filldream.fastboot.base.response.pc.MenuDTO;
import com.filldream.fastboot.common.entity.B;
import com.filldream.fastboot.common.entity.ErrorCode;
import com.filldream.fastboot.common.util.Assert;
import com.filldream.fastboot.common.util.ListUtil;
import com.filldream.fastboot.common.util.TransferUtil;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import javax.annotation.Resource;
import java.util.*;

@Service
@Transactional(rollbackFor = Exception.class)
public class MenuManager {

    /**
     * 菜单与角色规约
     * Role的PID为父级角色ID，若为0表示超级管理员角色，有且只有一个；
     */

    @Resource
    private MenuMapper menuMapper;

    @Resource
    private RoleMenuMapper roleMenuMapper;

    //获取详情
    public Menu getNoDelById(Long menuId){
        Menu menu = menuMapper.selectById(menuId);
        if( menu != null && menu.getIsDel().equals(1)){
            return null;
        }
        return menu;
    }

    public Menu getById(Long menuId){
        return menuMapper.selectById(menuId);
    }




    //添加菜单
    public Menu addMenu(Menu menu){
        menu.setMenuRank( getSort( menu.getParentId() ) );
        menu.setCreateTime(new Date());


        Menu parent = menuMapper.selectById(menu.getParentId());
        if( parent != null ){
            menu.setParentName( parent.getName() );
        }

        return  menuMapper.insert(menu)>0 ? menu : null;
    }

    //更新菜单
    public Menu updateMenu(Menu menu){
        Menu oldMenu = menuMapper.selectById(menu.getId());
        if( menu.getParentId() != null && !oldMenu.getParentId().equals(menu.getParentId()) ){
            Menu parent = menuMapper.selectById(menu.getParentId());
            if( parent != null ){
                menu.setParentName( parent.getName() );
            }
        }

        //修改了我的话，我的下级的父级名称也要修改
        if( !oldMenu.getName().equals( menu.getName() ) ){
            List<Menu> menus = menuMapper.selectList(new QueryWrapper<Menu>().eq("is_del", 0).eq("parent_id", menu.getId()));
            for (Menu childItem : menus) {
                childItem.setParentName( menu.getName() );
                menuMapper.updateById(childItem);
            }
        }

        menu.setUpdateTime(new Date());
        return  menuMapper.updateById(menu)>0 ? menuMapper.selectById(menu.getId()) : null;
    }

    //移动菜单
    public B moveMenu(MoveMenuSTO moveMenuSTO) {
        Menu menu = menuMapper.selectById(moveMenuSTO.getId());
        QueryWrapper<Menu> example = new QueryWrapper();
        example.eq("is_del",0).eq("parent_id",menu.getParentId());
        //上移
        if(moveMenuSTO.getMoveType().equals(1)){
            example.orderByDesc("menu_rank");
            example.le("menu_rank",menu.getMenuRank());
        }else{
            example.orderByAsc("menu_rank");
            example.ge("menu_rank",menu.getMenuRank());
        }
        example.last( " limit 0,2");
        List<Menu> menus = menuMapper.selectList(example);
        if(menus.size() < 2){
            return B.fail("无法移动，已经到顶或到底啦~");
        }else{
            Menu one = menus.get(0);
            Menu two = menus.get(1);
            Integer temp = two.getMenuRank();

            two.setMenuRank(one.getMenuRank());
            one.setMenuRank(temp);
            menuMapper.updateById(one);
            menuMapper.updateById(two);
            return B.success();
        }
    }

    /**
     * @author RickSun
     * @Description 删除菜单
     **/
    public Integer delMenu(Long menuId){
        Menu nowMenu = menuMapper.selectById(menuId);
        Assert.isNull( nowMenu ,ErrorCode.BASE_ERR.reMsg("当前菜单不存在"));

        //删除自己
        Menu menu = updateMenu(nowMenu.setIsDel(1));
        List<Menu> menus = new ArrayList<>();
        menus = getChildMenuList(menu, menus);

        if( menus.size() == 1 && menus.get(0).getId().equals(menuId) ){ //等于自己
            //删除角色关联
            roleMenuMapper.delete(new QueryWrapper<RoleMenu>().eq("menu_id", menuId));
        }else{
            Assert.checkBoolean( false,ErrorCode.DELETE_SUBMENU_ERR.reMsg(menus.size()-1+"个") );
        }
        return 1;
    }

    /**
     * 查询直属菜单
     * @param parentId  父级MenuId
     * @return
     */
    public List<Menu> getDirectMenuList(Long parentId){
        List<Menu> menus = menuMapper.selectList(
                new QueryWrapper<Menu>().eq("is_del",0)
                        .eq("parent_id",parentId)
                        .orderByAsc("menu_rank")
        );
        return menus;
    }





    //递归获取下级菜单列表
    public List<Menu> getChildMenuList(Menu menu,List<Menu> resultList){
        Menu sql = new Menu();
        sql.setId(menu.getParentId());
        sql.setIsDel(0);
        resultList.add(menu);
        List<Menu> directMenuList = getDirectMenuList(menu.getId());
        if( directMenuList != null && !directMenuList.isEmpty() ){
            for (Menu item : directMenuList) {
                getChildMenuList(item,resultList);
            }
        }else{
            return resultList;
        }
        return resultList;
    }


    public List<Menu> getAllMenuList(){
        return menuMapper.selectList( new QueryWrapper<Menu>().eq("is_del",0).orderByAsc("menu_rank") );
    }


    //获取排序
    private Integer getSort(Long parentId){
        List<Menu> menus = menuMapper.selectList(
                new QueryWrapper<Menu>().eq("is_del",0)
                        .eq("parent_id",parentId)
                        .orderByDesc("menu_rank").last(" limit 0,1")
        );
        if(menus.isEmpty()){
            return 1;
        }else{
            return menus.get(0).getMenuRank() + 1;
        }
    }


    //分类排序
    public List<MenuDTO> toTreeList(List<Menu> list, List<Long> checkIds){

        //排序
        ListUtil.sortByMoreParam(list,new String[]{"menu_rank"},new Boolean[]{false});

        Map<Long,MenuDTO> map =new HashMap<>();
        Map<Long,Boolean> isChildMap = new HashMap<>();

        List<MenuDTO> menuList = TransferUtil.changeToList(list, MenuDTO.class);
        for (MenuDTO item : menuList) {
            item.setChildren(new ArrayList<>());
            map.put(item.getId(),item);
            isChildMap.put(item.getId(),false);
        }

        for (MenuDTO item : menuList) {
            if(checkIds != null){
                item.setIsCheck(checkIds.contains(item.getId()));
            }
            Long parentId = item.getParentId();
            if(!parentId.equals(0L)){
                MenuDTO parent = map.get(parentId);
                List<MenuDTO> children = parent.getChildren();
                children.add(item);
                isChildMap.put(item.getId(),true);

            }
        }

        //遍历Map
        List<MenuDTO> result = new ArrayList<>();
        for (Map.Entry<Long, MenuDTO> entry : map.entrySet()) {
            Long id = entry.getKey();
            MenuDTO value = entry.getValue();
            if( !isChildMap.get(id)  ){
                result.add(value);
            }

        }

        Collections.sort(result, new Comparator<MenuDTO>() {
            @Override
            public int compare(MenuDTO u1, MenuDTO u2) {
                if (u1.getMenuRank() > u2.getMenuRank()) {
                    return 1;
                }
                if ( u1.getMenuRank().equals( u2.getMenuRank() ) ) {
                    return 0;
                }
                return -1;
            }
        });

        return result;

    }







//    public List<Tree<String>> getMenuList() {
//
//        List<Menu> menus = menuMapper.selectList(new QueryWrapper<Menu>().eq("is_del", 0).eq("is_menu", 1).orderByDesc("menu_rank"));
//        List<MenuDTO> resultList = TransferUtil.changeToList(menus, MenuDTO.class);
//
//        TreeNodeConfig treeNodeConfig = new TreeNodeConfig();
//        treeNodeConfig.setWeightKey("negativeMenuRank");
//        treeNodeConfig.setIdKey("id");
//        treeNodeConfig.setChildrenKey("children");
//        treeNodeConfig.setNameKey("name");
//
//        List<Tree<String>> treeNodes = TreeUtil.build(resultList, "0", treeNodeConfig,
//                (treeNode, tree) -> {
//                    tree.setId(treeNode.getId()+"");
//                    tree.setParentId(treeNode.getParentId()+"");
//                    tree.setWeight(treeNode.getNegativeMenuRank());
//                    tree.setName(treeNode.getName());
//
//                    tree.putExtra("menuUrl",treeNode.getMenuUrl());
//                    tree.putExtra("icon",treeNode.getIcon());
//                    tree.putExtra("label",treeNode.getName());
//                    tree.putExtra("menuRank",treeNode.getMenuRank());
//                    tree.putExtra("code",treeNode.getCode());
//                    tree.putExtra("isMenu",treeNode.getIsMenu());
//                });
//
//        return treeNodes;
//    }

    public List<Tree<String>> getMenuList(Integer isMenu) {
        LambdaQueryWrapper<Menu> sql = new LambdaQueryWrapper<>();
        sql.eq(Menu::getIsDel,0);
        sql.orderByAsc(Menu::getMenuRank);
        if( isMenu != null ){
            sql.eq(Menu::getIsMenu,isMenu);
        }
        List<Menu> menus = menuMapper.selectList(sql);


        List<MenuDTO> resultList = new ArrayList<>();
        for (Menu item : menus) {
            resultList.add( TransferUtil.changeToObj(item, MenuDTO.class) );
        }

        TreeNodeConfig treeNodeConfig = new TreeNodeConfig();
        treeNodeConfig.setWeightKey("menuRank");
        treeNodeConfig.setIdKey("id");
        treeNodeConfig.setChildrenKey("children");
        treeNodeConfig.setNameKey("name");
        treeNodeConfig.setParentIdKey("parentId");

        List<Tree<String>> treeNodes = TreeUtil.build(resultList, "0", treeNodeConfig,
                (treeNode, tree) -> {
                    tree.setId(treeNode.getId()+"");
                    tree.setParentId(treeNode.getParentId()+"");
                    tree.setWeight(treeNode.getNegativeMenuRank());
                    tree.setName(treeNode.getName());

                    tree.putExtra("menuUrl",treeNode.getMenuUrl());
                    tree.putExtra("icon",treeNode.getIcon());
                    tree.putExtra("label",treeNode.getName());
                    tree.putExtra("menuRank",treeNode.getMenuRank());
                    tree.putExtra("code",treeNode.getCode());
                    tree.putExtra("isMenu",treeNode.getIsMenu());
                });

        return treeNodes;
    }
}
